package com.a1anwang.okble.demo.ability;

import com.a1anwang.okble.client.core.OKBLEDevice;
import com.a1anwang.okble.client.core.OKBLEDeviceImp;
import com.a1anwang.okble.client.core.OKBLEDeviceListener;
import com.a1anwang.okble.client.scan.BLEScanResult;
import com.a1anwang.okble.common.LogUtils;
import com.a1anwang.okble.common.OKBLECharacteristicModel;
import com.a1anwang.okble.common.OKBLEServiceModel;
import com.a1anwang.okble.demo.APP;
import com.a1anwang.okble.demo.ResourceTable;
import com.a1anwang.okble.demo.base.BaseAbility;
import com.a1anwang.okble.demo.widget.ChildListContainer;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.*;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
import ohos.agp.window.service.DisplayManager;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by a1anwang.com on 2018/5/22.
 */

public class DeviceDetailAbility extends BaseAbility implements OKBLEDeviceListener {
    private static final int CONNECTED = 0;
    private static final int DISCONNECTED = 1;
    CommonDialog dialog;
    BLEScanResult bleScanResult;
    OKBLEDevice okbleDevice;
    List<OKBLEServiceModel> serviceModels;
    List<OKBLECharacteristicModel> characteristicModels;
    ListContainer listContainer;
    ItemProvider provider;
    DirectionalLayout btnLeft;
    OKBLEServiceModel characteristicModel = null;
    EventRunner runner = EventRunner.create(true);// create()的参数是true时，则为托管模式
    MyEventHandler handler = new MyEventHandler(runner);
    EventHandler eventHandler = new EventHandler(EventRunner.getMainEventRunner());
    private final String TAG = "DeviceDetailAbility";
    private Text tvTitle;
    private Text tvRight;

    @Override
    protected void onStop() {
        super.onStop();
        if (okbleDevice != null) {
            okbleDevice.remove();
            okbleDevice = null;
        }
    }


    @Override
    protected void onActive() {
        super.onActive();
        if (okbleDevice != null) {
            updateDeviceStatus();
        }
    }

    @Override
    public boolean isFullScreen() {
        return false;
    }

    @Override
    public void setContentLayout() {
        setUIContent(ResourceTable.Layout_ability_device_detail);
    }

    @Override
    public void beforeInitView() {
    }

    @Override
    public void initView() {
        bleScanResult = APP.getApp().getScanResult();
        setHeadVisibility(Component.VISIBLE);
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_list);
        tvTitle = (Text) findComponentById(ResourceTable.Id_tv_title);
        tvRight = (Text) findComponentById(ResourceTable.Id_tv_right);
        btnLeft = (DirectionalLayout) findComponentById(ResourceTable.Id_btn_left);
        btnLeft.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                onBackPressed();
            }
        });
        provider = new ItemProvider(this);
        if (bleScanResult != null && okbleDevice != null) {
            okbleDevice = new OKBLEDeviceImp(mContext, bleScanResult);
            okbleDevice.addDeviceListener(this);
            okbleDevice.connect(true);

            tvTitle.setText(bleScanResult.getMacAddress());
            updateDeviceStatus();
        }
        listContainer.setItemProvider(provider);
        tvRight.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                switch (okbleDevice.getDeviceStatus()) {
                    case DEVICE_STATUS_CONNECTED:
                        int screenWidht = DisplayManager.getInstance().getDefaultDisplay(mContext).get().getAttributes().width;
                        int screenHeight = DisplayManager.getInstance().getDefaultDisplay(mContext).get().getAttributes().height;
                        dialog = new CommonDialog(mContext);
                        Component layout = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_dis_connent, null, true);
                        dialog.setAlignment(TableLayout.Alignment.ALIGNMENT_BOTTOM);
                        dialog.setTransparent(true);
                        dialog.setContentCustomComponent(layout);
                        dialog.setSize(screenWidht, screenHeight);
                        dialog.show();
                        Text tvYes = (Text) layout.findComponentById(ResourceTable.Id_yes);
                        Text tvNo = (Text) layout.findComponentById(ResourceTable.Id_no);
                        tvYes.setClickedListener(new Component.ClickedListener() {
                            @Override
                            public void onClick(Component component) {
                                dialog.hide();
                                okbleDevice.disConnect(false);
                            }
                        });
                        tvNo.setClickedListener(new Component.ClickedListener() {
                            @Override
                            public void onClick(Component component) {
                                dialog.hide();
                            }
                        });
                        break;
                    case DEVICE_STATUS_DISCONNECTED:
                        okbleDevice.connect(true);
                        updateDeviceStatus();
                        break;
                    default:
                        break;
                }
            }
        });
    }

    @Override
    public void afterInitView() {

    }

    @Override
    public void onClickEvent(Component v) {

    }

    @Override
    public void onHeadRightClick(Component v) {
        if (okbleDevice.getDeviceStatus() == OKBLEDeviceImp.DeviceStatus.DEVICE_STATUS_CONNECTED) {
            final CommonDialog commonDialog = new CommonDialog(getContext());
            commonDialog.setTitleText("")
                    .setContentText(getString(ResourceTable.String_caution_want_to_disconnect))
                    .setButton(0, "yes", new IDialog.ClickedListener() {
                        @Override
                        public void onClick(IDialog iDialog, int i) {
                            commonDialog.destroy();
                            okbleDevice.disConnect(false);
                        }
                    }).setButton(1, "no", new IDialog.ClickedListener() {
                        @Override
                        public void onClick(IDialog iDialog, int i) {
                            commonDialog.destroy();
                        }
                    }
            );
            commonDialog.show();
        } else if (okbleDevice.getDeviceStatus() == OKBLEDeviceImp.DeviceStatus.DEVICE_STATUS_DISCONNECTED) {
            okbleDevice.connect(true);
            updateDeviceStatus();
        }
    }

    private void updateDeviceStatus() {
        switch (okbleDevice.getDeviceStatus()) {
            case DEVICE_STATUS_CONNECTED:
                tvRight.setText("Connected");
                break;
            case DEVICE_STATUS_CONNECTING:
                tvRight.setText("Connecting");
                break;
            case DEVICE_STATUS_DISCONNECTED:
                tvRight.setText("Disconnected");
                break;
            default:
                break;
        }
    }


    /**
     * MyEventHandler
     *
     * @since 2021-05-14
     */
    class MyEventHandler extends EventHandler {

        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event == null) {
                return;
            }
            switch (event.eventId) {
                case CONNECTED:
                    eventHandler.postTask(new Runnable() {
                        @Override
                        public void run() {
                            if (okbleDevice != null) {
                                updateDeviceStatus();
                            }
                        }
                    });
                    serviceModels = okbleDevice.getServiceModels();
                    characteristicModels = new ArrayList<>();
                    try {
                        if (serviceModels != null) {
                            for (OKBLEServiceModel model : serviceModels) {
                                for (OKBLECharacteristicModel characteristicModel : model.getCharacteristicModels()) {
                                    characteristicModels.add(characteristicModel);
                                }
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    eventHandler.postTask(new Runnable() {
                        @Override
                        public void run() {
                            provider.notifyDataChanged();
                        }
                    });
                    break;
                case DISCONNECTED:

                    eventHandler.postTask(new Runnable() {
                        @Override
                        public void run() {
                            if (okbleDevice != null) {
                                updateDeviceStatus();
                            }
                        }
                    });
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void onConnected(String deviceTag) {
        LogUtils.e(TAG, " onConnected:" + deviceTag);
        handler.sendEvent(CONNECTED);


    }

    @Override
    public void onDisconnected(String deviceTag) {
        handler.sendEvent(DISCONNECTED);
    }

    @Override
    public void onReadBattery(String deviceTag, int battery) {

    }

    @Override
    public void onReceivedValue(String deviceTag, String uuid, byte[] value) {

    }

    @Override
    public void onWriteValue(String deviceTag, String uuid, byte[] value, boolean success) {

    }

    @Override
    public void onReadValue(String deviceTag, String uuid, byte[] value, boolean success) {

    }

    @Override
    public void onNotifyOrIndicateComplete(String deviceTag, String uuid, boolean enable, boolean success) {

    }


    /**
     * 外层列表的Provider
     *
     * @since 2021-05-14
     */
    private class ItemProvider extends BaseItemProvider {

        ItemProvider(Ability ability) {
        }

        @Override
        public int getCount() {
            return serviceModels == null ? 0 : serviceModels.size();
        }

        @Override
        public Object getItem(int i) {
            return null;
        }

        @Override
        public long getItemId(int i) {
            return 0;
        }

        @Override
        public Component getComponent(int i, Component convertView, ComponentContainer componentContainer) {
            GroupViewHolder groupViewHolder = null;
            if (convertView == null) {
                convertView = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_item_servicemodel, null, false);
                groupViewHolder = new GroupViewHolder();
                groupViewHolder.tvTitle = (Text) convertView.findComponentById(ResourceTable.Id_tv_title);
                groupViewHolder.tvDesc = (Text) convertView.findComponentById(ResourceTable.Id_tv_desc);
                groupViewHolder.childlist = (ChildListContainer) convertView.findComponentById(ResourceTable.Id_childlist);
                convertView.setTag(groupViewHolder);
            } else {
                groupViewHolder = (GroupViewHolder) convertView.getTag();
            }
            characteristicModel = serviceModels.get(i);
            groupViewHolder.tvTitle.setText(characteristicModel.getUuid());
            groupViewHolder.tvDesc.setText(characteristicModel.getDesc());
            groupViewHolder.childlist.setPosition(i);
            groupViewHolder.childlist.setModel(serviceModels.get(i).getCharacteristicModels());

            groupViewHolder.childlist.setItemProvider(new ChildProvider(groupViewHolder.childlist.getModel()));

            GroupViewHolder finalGroupViewHolder = groupViewHolder;
            groupViewHolder.childlist.setItemClickedListener(new ListContainer.ItemClickedListener() {
                @Override
                public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {
                    OKBLECharacteristicModel characteristicModel = finalGroupViewHolder.childlist.getModel().get(i);
                    getApplication().okbleDevice = okbleDevice;

                    Intent intent = new Intent();
                    APP.getApp().setCharacteristicModel(characteristicModel);
                    Operation operation = new Intent.OperationBuilder()
                            .withBundleName(getBundleName())
                            .withAbilityName(CharacteristicAbility.class.getName())
                            .build();
                    intent.setOperation(operation);
                    startAbility(intent);
                }
            });
            return convertView;
        }

        /**
         * ChildListContainer 的Provider
         *
         * @since 2021-05-14
         */
        private class ChildProvider extends BaseItemProvider {

            private List<OKBLECharacteristicModel> characteristicModel;

            private ChildProvider(List<OKBLECharacteristicModel> characteristicModel) {
                this.characteristicModel = characteristicModel;
            }

            @Override
            public int getCount() {
                return characteristicModel == null ? 0 : characteristicModel.size();
            }

            @Override
            public Object getItem(int i) {
                return null;
            }

            @Override
            public long getItemId(int i) {
                return 0;
            }

            @Override
            public Component getComponent(int i, Component component, ComponentContainer componentContainer) {
                ChildViewHolder childViewHolder = null;
                if (component == null) {
                    childViewHolder = new ChildViewHolder();
                    component = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_item_characteristicmodel, null, false);
                    childViewHolder.tvTitle = (Text) component.findComponentById(ResourceTable.Id_tv_title);
                    childViewHolder.tvDesc = (Text) component.findComponentById(ResourceTable.Id_tv_desc);
                    childViewHolder.tvRead = (DirectionalLayout) component.findComponentById(ResourceTable.Id_tv_read);
                    childViewHolder.tvWrite = (DirectionalLayout) component.findComponentById(ResourceTable.Id_tv_write);
                    childViewHolder.tvWriteNoResponse = (DirectionalLayout) component.findComponentById(ResourceTable.Id_tv_write_no_response);
                    childViewHolder.tvNotify = (DirectionalLayout) component.findComponentById(ResourceTable.Id_tv_notify);
                    childViewHolder.tvIndicate = (DirectionalLayout) component.findComponentById(ResourceTable.Id_tv_indicate);
                    component.setTag(childViewHolder);
                } else {
                    childViewHolder = (ChildViewHolder) component.getTag();
                }
                childViewHolder.tvTitle.setText(characteristicModel.get(i).getUuid());
                childViewHolder.tvDesc.setText(characteristicModel.get(i).getDesc());
                childViewHolder.tvRead.setVisibility(characteristicModel.get(i).isCanRead() ? Component.VISIBLE : Component.HIDE);
                childViewHolder.tvWrite.setVisibility(characteristicModel.get(i).isCanWrite() ? Component.VISIBLE : Component.HIDE);
                childViewHolder.tvWriteNoResponse.setVisibility(characteristicModel.get(i).isCanWriteNoResponse() ? Component.VISIBLE : Component.HIDE);
                childViewHolder.tvNotify.setVisibility(characteristicModel.get(i).isCanNotify() ? Component.VISIBLE : Component.HIDE);
                childViewHolder.tvIndicate.setVisibility(characteristicModel.get(i).isCanIndicate() ? Component.VISIBLE : Component.HIDE);
                return component;
            }
        }

        /**
         * GroupViewHolder 外层ViewHolder
         *
         * @since 2021-05-14
         */
        class GroupViewHolder {
            Text tvTitle;
            Text tvDesc;
            ChildListContainer childlist;
        }

        /**
         * ChildViewHolder 内层ViewHolder
         *
         * @since 2021-05-14
         */
        class ChildViewHolder {
            Text tvTitle;
            Text tvDesc;
            DirectionalLayout tvRead;
            DirectionalLayout tvWrite;
            DirectionalLayout tvWriteNoResponse;
            DirectionalLayout tvNotify;
            DirectionalLayout tvIndicate;
        }
    }
}
